package net.vinote.smart.platform.service.servlet;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.exception.PlatformException;
import net.vinote.smart.platform.module.database.DBFactory;
import net.vinote.smart.platform.module.database.DBTransaction;
import net.vinote.smart.platform.module.database.bo.BizObject;
import net.vinote.smart.platform.module.log.RunLogger;
import net.vinote.smart.platform.service.DWException;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.bean.DataWindowCatalog;
import net.vinote.smart.platform.service.dw.DataWindow;
import net.vinote.smart.platform.service.dw.handler.CommonHandler;
import net.vinote.smart.platform.service.dw.handler.HandlerPerimissionAnnotation;
import net.vinote.smart.platform.service.dw.handler.VirtualCommonHandler;
import net.vinote.smart.platform.service.util.Permission;
import net.vinote.smart.platform.service.util.Permission.PermissionUtil;

import org.json.JSONArray;
import org.json.JSONObject;

public class DataWindowServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doPost(req, resp);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String doNo = req.getParameter("doNo");
		String action = req.getParameter("action");
		DataWindowCatalog dwBo = SRE.getDataWindowCatalog(doNo);
		String handlerName = dwBo.getHandler();
		boolean isVirtual = DataWindow.VIRTUAL_FLAG.equalsIgnoreCase(dwBo
				.getMainTable());
		CommonHandler handler = getHandlerClass(handlerName, isVirtual);
		handler.setDoNo(doNo);
		handler.setRequest(req);
		Map<String, BizObject> boMap = getBizObjectList(req);

		// 生成响应数据
		JSONObject json = new JSONObject();
		try {
			if ("save".equals(action)) {
				if (isVirtual) {// 处理虚拟模板
					for (String key : boMap.keySet()) {
						((VirtualCommonHandler) handler).doVirtual(boMap
								.get(key));
					}
				} else {// 处理实体模板保存事件
					doSaveMethod(doNo, handler, boMap, req);
				}
				// 构建响应数据
				JSONArray dataArray = new JSONArray();
				for (Entry<String, BizObject> entry : boMap.entrySet()) {
					dataArray.put(entry.getValue().getJSON());
				}
				json.put("data", dataArray);
			} else if ("delete".equals(action)) {
				doDeleteMethod(handler, boMap, req);
			} else {
				throw new PlatformException("unsupport action " + action);
			}
			json.put("success", true);
		} catch (Exception e) {
			RunLogger.getLogger().log(Level.WARNING, e.getMessage(), e);
			json.put("success", false);
			json.put("message", e.getMessage());
		}

		resp.getWriter().print(json.toString());
	}

	/**
	 * 删除一条表记录,暂时仅支持单条删除
	 * 
	 * @param handler
	 * @return
	 * @throws SQLException
	 */
	private void doDeleteMethod(CommonHandler handler,
			Map<String, BizObject> boMap, HttpServletRequest request)
			throws SQLException {
		// 是否启用了防火墙进行 权限校验
		if (SRE.getSystemParameter().getFirewall() == PlatformConst.Yes) {
			HandlerPerimissionAnnotation annotation = handler.getClass()
					.getAnnotation(HandlerPerimissionAnnotation.class);
			if (annotation == null) {
				throw new PlatformException("未指定权限,操作存在隐患!");
			}
			Permission permission = annotation.delete();
			if (permission == null
					|| ((permission.value() == null || permission.value().length == 0) && (permission
							.ExtendedPermision() == null || permission
							.ExtendedPermision().length == 0))) {
				throw new PlatformException("未指定权限,操作存在隐患!");
			}
			if (!PermissionUtil.hasPermission(permission, request)) {
				throw new PlatformException("权限校验失败" + permission);
			}
		}

		DBTransaction tx = null;
		try {
			tx = DBFactory.getFactory().getTransaction();
			for (String key : boMap.keySet()) {
				handler.doDelete(boMap.get(key), tx);
			}
			tx.commit();
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new PlatformException(e);
		} finally {
			if (tx != null) {
				tx.close();
				tx = null;
			}
		}
	}

	/**
	 * @param req
	 * @return
	 */
	private Map<String, BizObject> getBizObjectList(HttpServletRequest req) {
		Map<String, BizObject> boMap = new HashMap<String, BizObject>();
		@SuppressWarnings("unchecked")
		Enumeration<String> paramEnum = req.getParameterNames();
		String param, attr, index;
		String[] temp;
		BizObject bo;
		while (paramEnum.hasMoreElements()) {
			param = paramEnum.nextElement();
			if (param.equals("doNo") || "action".equals(param)) {
				continue;
			}
			// 标准的实体字段格式为 X.field
			if (param.indexOf(".") != -1) {// 读取实体字段
				temp = param.substring(param.indexOf(".") + 1).split("@");
			} else {
				temp = param.split("@");
			}
			attr = temp[0];
			if (temp.length != 2) {// Info页面无索引值
				index = "0";
			} else {
				index = temp[1];
			}
			bo = boMap.get(index);
			if (bo == null) {
				bo = new BizObject();
				boMap.put(index, bo);
			}
			String paramVal = getParameterValue(req.getParameterValues(param));
			bo.setAttribute(attr, paramVal);
		}
		return boMap;
	}

	private String getParameterValue(String[] parameterValues) {
		if (parameterValues == null) {
			return null;
		}
		StringBuffer sb = new StringBuffer();
		int length = parameterValues.length;
		int i = 0;
		if (length > 0) {
			sb.append(parameterValues[i]);
			while (++i < length) {
				sb.append(',').append(parameterValues[i]);
			}
		}
		return sb.toString();
	}

	/**
	 * 对模板中的数据进行保存操作
	 * 
	 * @param doNo
	 * @param handler
	 * @param boMap
	 * @throws SQLException
	 */
	private void doSaveMethod(String doNo, CommonHandler handler,
			Map<String, BizObject> boMap, HttpServletRequest request)
			throws SQLException {
		DBTransaction tx = null;
		try {
			tx = DBFactory.getFactory().getTransaction();
			boolean insertChecked = false;
			boolean updateChecked = false;
			boolean firewall = SRE.getSystemParameter().getFirewall() == PlatformConst.Yes;
			for (String key : boMap.keySet()) {
				boolean insert = "true".equals(boMap.get(key).getAttribute(
						"isInsert"));
				// 是否启用了防火墙进行 权限校验
				if (firewall
						&& (insert && !insertChecked || !insert
								&& !updateChecked)) {

					HandlerPerimissionAnnotation annotation = handler
							.getClass().getAnnotation(
									HandlerPerimissionAnnotation.class);
					if (annotation == null) {
						throw new PlatformException("未指定权限,操作存在隐患!请为"
								+ handler.getClass().getName() + "配置权限!");
					}
					Permission permission = insert ? annotation.insert()
							: annotation.update();
					if (permission == null
							|| ((permission.value() == null || permission
									.value().length == 0) && (permission
									.ExtendedPermision() == null || permission
									.ExtendedPermision().length == 0))) {
						throw new PlatformException("未指定"
								+ (insert ? "新增" : "更新") + "权限,操作存在隐患!请为"
								+ handler.getClass().getName() + "配置权限!");
					}
					if (!PermissionUtil.hasPermission(permission, request)) {
						throw new PlatformException("权限校验失败" + permission);
					}
					if (insert) {
						insertChecked = true;
					} else {
						updateChecked = true;
					}
				}

				handler.setInsert(insert);
				handler.doSave(tx, boMap.get(key), doNo);
			}
			tx.commit();
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new PlatformException(e);
		} finally {
			if (tx != null) {
				tx.close();
				tx = null;
			}
		}
	}

	/**
	 * 实例化一个Handler类用于处理模板中的数据
	 * 
	 * @param handlerName
	 * @return
	 */
	private CommonHandler getHandlerClass(String handlerName, boolean virtual) {
		CommonHandler handlerClass = null;
		if (handlerName == null || "".equals(handlerName.trim())) {
			return virtual ? new VirtualCommonHandler() : new CommonHandler();
		}
		try {
			Object obj = Class.forName(handlerName).newInstance();
			if (virtual && (obj instanceof VirtualCommonHandler)) {
				handlerClass = (VirtualCommonHandler) obj;
			} else if (!virtual && (obj instanceof CommonHandler)) {
				handlerClass = (CommonHandler) obj;
			} else {
				throw new DWException("无效Handler类" + handlerName);
			}
		} catch (Exception e) {
			RunLogger.getLogger().log(Level.SEVERE, e.getMessage(), e);
		}
		return handlerClass;
	}
}
